import { computed, nextTick, onMounted, reactive, ref, Ref, set, watch } from 'vue'
import { debounce } from 'lodash'
import config from '@/config'
import { createId, scrollIntoView } from '@/utils'
import { Widget } from '@/models'

export default function useSelectOptions(data: Ref<Widget>) {
  /** 选项配置 */
  const optionConfig = config.selectOption

  /** 是否只读 */
  const readonly = computed(() => !data.value.isUse)

  /** 选项列表 */
  const options = ref<{ label: string; id: string }[]>([])

  /** 初始选项数据 */
  function init() {
    options.value = data.value.selectOptions.map(label => ({ id: createId(), label }))
  }

  onMounted(init)

  /** 下拉选项列表 */
  const selectOptions = computed(() => options.value.map(option => option.label))

  /** 选项变更后同步到控件 */
  watch(
    selectOptions,
    debounce((list: string[]) => {
      data.value.selectOptions = list
    }, 300)
  )

  /** 激活的索引 */
  const activeIndex = computed({
    set(index: number) {
      set(data.value.extra, 'activeIndex', index)
    },

    get() {
      return (data.value.extra.activeIndex as number) ?? -1
    }
  })

  /** 新增按钮 */
  const addButton = reactive({
    /** 是否可见 */
    visible: computed(() => data.value.isSet),

    /** 禁用提示 */
    disabledTips: computed(() => {
      const { max } = optionConfig
      return options.value.length < max ? '' : `最多添加${max}个选项`
    })
  })

  /** 清除控件值 */
  function clear() {
    data.value.value = ''
  }

  return reactive({
    /** 选项列表 */
    options,

    /** 初始选项数据 */
    init,

    /** 激活的索引 */
    activeIndex,

    /** 是否只读 */
    readonly,

    /** 最大长度 */
    maxLength: optionConfig.maxLength,

    /** 新增按钮 */
    addButton,

    /** 新增选项 */
    async add() {
      if (addButton.disabledTips) return

      const list = options.value

      list.push({ label: `选项${list.length + 1}`, id: createId() })

      await nextTick()

      // 滚动到最后一个
      scrollIntoView('.fa-widget-setting .group-option:last-child')
    },

    /** 选项更改 */
    change(index: number) {
      const widget = data.value
      const options = widget.selectOptions
      const selectIndex = options.findIndex(option => option && option === widget.value)

      // 关联更新选中值
      if (widget.value && selectIndex === -1) {
        widget.value = options[index]
      }
    },

    /** 是否删除选项 */
    removable: computed(() => data.value.isSet && options.value.length > 1),

    /** 移除选项 */
    remove(index: number) {
      const list = options.value
      const option = list[index]

      list.splice(index, 1)

      // 如果删除项为当前选中，则清空
      option.label === data.value.value && clear()
    },

    /** 清除控件值 */
    clear
  })
}
